package ga.mutation;

import ga.GARun;
import ga.individuals.Individual;

import java.util.Collection;
import java.util.LinkedList;
import java.util.Random;

public class ClassicMutation implements MutationMethod {
	
	@Override
	public Collection<Individual> method(Collection<Individual> individuals) {
		Collection<Individual> newIndividuals = new LinkedList<Individual>();
		Double pMut = GARun.mutationProb;
		Random random;
		for (Individual individual: individuals) {
			Double individualValue = individual.getIndividualValue();
			Long individualValueBits = Double.doubleToRawLongBits(individualValue);
			random = new Random(System.currentTimeMillis());
			for (int i = 0; i < GARun.bitsInDouble; i++) {
				if (random.nextDouble() < pMut) {
					individualValueBits = changeBit(individualValueBits.longValue(), i);
				}
			}
			newIndividuals.add(new Individual(Double.longBitsToDouble(individualValueBits)));
		}
		return newIndividuals;
	}

	private Long changeBit(long individualValueBits, int i) {
		long bitToChange = 0x0000000000000001L << i;
		if ((individualValueBits & bitToChange) == 0) {
			/* El bit a cambiar es un 0 */
			return new Long(individualValueBits | bitToChange);
		} else {
			/* El bit a cambiar es un 1 */
			return new Long(individualValueBits & (~bitToChange));
		}
	}

}
